home *** CD-ROM | disk | FTP | other *** search
Text File | 1996-06-22 | 73.2 KB | 2,209 lines | [TEXT/CWIE] |
- /*
- File: AppleEventUtilities.cp
-
- Contains: C++ Wrappers for Apple Event manager
-
- */
-
- #ifndef __APPLEEVENTUTILITIES__
- #include "AppleEventUtilities.h"
- #endif
-
- #ifndef __ASREGISTRY__
- #include <ASRegistry.h>
- #endif
-
- #ifndef Exceptions_h
- #include "Exceptions.h"
- #endif
-
- #ifndef __OSUTILS__
- #include <OSUtils.h>
- #endif
-
- #ifndef __SCRIPT__
- #include <Script.h>
- #endif
-
- #ifndef __APPLEEVENTS__
- #include <AppleEvents.h>
- #endif
-
- #ifndef __AEOBJECTS__
- #include <AEObjects.h>
- #endif
-
- #ifndef __ALIASES__
- #include <Aliases.h>
- #endif
-
- #ifndef __AEOBJECTPACKING__
- #include <AEPackObject.h>
- #endif
-
- #ifndef __AEREGISTRY__
- #include <AERegistry.h>
- #endif
-
- #ifndef __GESTALTEQU__
- #include <GestaltEqu.h>
- #endif
-
- #pragma segment AEMStuff
-
-
- MakeTokenDescriptorProcPtr gNullContainerCreationProc = nil;
- ProcessDescriptorProcPtr gPreResolveProc = nil;
- MergeTokensProcPtr gMergeTokensProc = nil;
-
- short TDescriptor::fCallbackFlags = kAEIDoMinimum;
-
- //----------------------------------------------------------------------------------------
- // InstallNullContainerCreationProc:
- //
- // The null container creation proc is used by TDescriptor::Resolve whenever it receives
- // a null descriptor to resolve. This function is used to create a token for the null
- // container.
- //----------------------------------------------------------------------------------------
- void InstallNullContainerCreationProc(MakeTokenDescriptorProcPtr creationProc)
- {
- gNullContainerCreationProc = creationProc;
- } // InstallNullContainerCreationProc
-
- //----------------------------------------------------------------------------------------
- // InstallPreResolveProc:
- //
- // The PreResolveProc is called by TDescriptor::Resolve before it actually calls
- // AEResolve. This allows special procs to handle things not understood by AEResolve
- // (alias records, for example).
- //----------------------------------------------------------------------------------------
- void InstallPreResolveProc(ProcessDescriptorProcPtr preResolveProc)
- {
- gPreResolveProc = preResolveProc;
- } // InstallPreResolveProc
-
- //----------------------------------------------------------------------------------------
- // InstallMergeTokensProc:
- //
- // The MergeTokensProc is called by TTokenDescriptor::AdoptToken whenever it needs to add
- // a token object to any token descriptor that already contains a token. The merge token
- // proc is provided with two TAbstractScriptableObject*'s; it must return a
- // TAbstractScriptableObject* that has adopted the two tokens passed to it.
- //----------------------------------------------------------------------------------------
- void InstallMergeTokensProc(MergeTokensProcPtr mergeTokensProc)
- {
- gMergeTokensProc = mergeTokensProc;
- } // InstallMergeTokensProc
-
- //----------------------------------------------------------------------------------------
- // CreateNullContainerToken:
- //----------------------------------------------------------------------------------------
- TTokenDescriptor CreateNullContainerToken()
- {
- TTokenDescriptor nullContainer;
-
- if(gNullContainerCreationProc != nil)
- nullContainer = (*gNullContainerCreationProc)();
-
- return nullContainer;
- } // CreateNullContainerToken
-
- //========================================================================================
- // CLASS TDescriptor
- //
- // Class TDescriptor is a wrapper class for AEDesc objects.
- //========================================================================================
-
-
- //----------------------------------------------------------------------------------------
- // TDescriptor::Dispose:
- //
- // Disposed of the descriptor and the data stored inside it.
- //----------------------------------------------------------------------------------------
- void TDescriptor::Dispose()
- {
- FailErr(AEDisposeDesc(*this));
- } // TDescriptor::Dispose
-
- //----------------------------------------------------------------------------------------
- // TDescriptor::AttemptCoercion:
- //
- // Try to coerce the type of the descriptor to something else. This method will
- // NOT fail if the coercion could not be done.
- //----------------------------------------------------------------------------------------
- OSErr TDescriptor::AttemptCoercion(DescType typeToCoerceTo)
- {
- OSErr err = noErr;
-
- if(this->DescriptorType() != typeToCoerceTo)
- {
- TDescriptor tempDescriptor;
-
- // If AECoerceDesc returns a non-zero result code, then
- // tempDescriptor will be typeNull, and we don't need to
- // worry about disposing of it.
- err = AECoerceDesc(*this,typeToCoerceTo,(AEDesc*)&tempDescriptor);
-
- if(err == noErr)
- {
- Try
- {
- Handle initialHandle = this->DataHandle();
- Handle coercedHandle = tempDescriptor.DataHandle();
-
- //
- // If doing a coerce-in-place, try to do a SetHandleSize
- // and then a BlockMove so that we end up using the same
- // handle when we exit as we had when we entered. To do
- // otherwise is to invite double-dispose/memory leak problems
- // if some other peice of code still has a reference to
- // the descriptor before it was coerced
- //
- if((initialHandle != nil) && (coercedHandle != nil))
- {
- Size coercedSize = GetHandleSize(coercedHandle);
- SetHandleSize(initialHandle, coercedSize);
- FailErr(MemError());
- BlockMove(*coercedHandle, *initialHandle, coercedSize);
- this->fDescriptorType = tempDescriptor.DescriptorType();
- tempDescriptor.Dispose();
- }
- //
- // There are a couple of rare cases (typeTrue and typeFalse)
- // where the data handle is nil
- //
- else
- {
- //
- // It's undesirable to go from a nil-handle to a non-nil
- // handle, or visa-versa. Don't do it. Use 'Coerce'
- // rather than 'CoerceInPlace' if this is necessary.
- //
- if((initialHandle != nil) || (coercedHandle != nil))
- DebugStr("\pPotentially undesirable coerce-in-place");
- //
- // Try to dispose of the old descriptor (ignoring errors)
- // and then plug in the values from the coerced descriptor
- //
- AEDisposeDesc(*this);
- this->AdoptDesc(tempDescriptor);
- }
- }
- Catch(err)
- {
- tempDescriptor.Dispose();
- }
- }
- }
-
- return err;
- } // TDescriptor::AttemptCoercion
-
- //----------------------------------------------------------------------------------------
- // TDescriptor::CoerceInPlace:
- //
- // Require that this object be coerced to the specified data type. This method will
- // fail if the coercion does not work.
- //----------------------------------------------------------------------------------------
- void TDescriptor::CoerceInPlace(DescType typeToCoerceTo)
- {
- FailErr(this->AttemptCoercion(typeToCoerceTo));
- } // TDescriptor::CoerceInPlace
-
- //----------------------------------------------------------------------------------------
- // TDescriptor::Coerce:
- //
- // Require that this object be coerced to the specified data type. This method will
- // fail if the coercion does not work.
- //----------------------------------------------------------------------------------------
- TDescriptor TDescriptor::Coerce(DescType typeToCoerceTo) const
- {
- TDescriptor coercedDescriptor;
-
- FailErr(AECoerceDesc(*this,typeToCoerceTo,coercedDescriptor));
-
- return coercedDescriptor;
- } // TDescriptor::Coerce
-
- //----------------------------------------------------------------------------------------
- // TDescriptor::CoerceToStandardType:
- //
- // This method attempts to coerce its data into some form of standard type
- // (e.g. typeChar or typeLongInteger). It is really annoying that someone can
- // invent yet another data type that is coercable to text or as a long integer,
- // but we wouldn't have any way to know that such a coercion should be attempted.
- // typeMagnitude and typeEnumeration could throw us for a loop too.
- //
- // ••• In short, I really hate this routine, but I'm not sure what else to do about it.
- //----------------------------------------------------------------------------------------
- void TDescriptor::CoerceToStandardType()
- {
- switch(this->DescriptorType())
- {
- case typeAEText:
- case typeIntlText:
- case typeStyledText:
- {
- this->CoerceInPlace(typeChar);
- break;
- }
-
- case typeShortInteger:
- {
- this->CoerceInPlace(typeLongInteger);
- break;
- }
- }
- } // TDescriptor::CoerceToStandardType
-
- //----------------------------------------------------------------------------------------
- // TDescriptor::Clone:
- //
- // Return an exact copy of this descriptor
- //----------------------------------------------------------------------------------------
- TDescriptor TDescriptor::Clone() const
- {
- TDescriptor clonedDescriptor;
-
- FailErr(AEDuplicateDesc(*this, (AEDesc*)&clonedDescriptor));
-
- return clonedDescriptor;
- } // TDescriptor::Clone
-
- //----------------------------------------------------------------------------------------
- // TDescriptor::CopyDesc:
- //----------------------------------------------------------------------------------------
- void TDescriptor::CopyDesc(const TDescriptor& desc)
- {
- FailErr(AEDuplicateDesc((AEDesc*)&desc, *this));
- } // TDescriptor::CopyDesc
-
- //----------------------------------------------------------------------------------------
- // TDescriptor::AdoptDesc:
- //----------------------------------------------------------------------------------------
- void TDescriptor::AdoptDesc(TDescriptor& desc)
- {
- //
- // It would be very tempting to set 'desc' to the null descriptor now
- // that we have adopted it here. That would be a bad idea, though, because
- // we might intend this descriptor to actually be just a reference to
- // the adopted desc, and not actually the new 'owner' of the data.
- //
- this->AdoptHandle(desc.DescriptorType(), desc.DataHandle());
- } // TDescriptor::AdoptDesc
-
- //----------------------------------------------------------------------------------------
- // TDescriptor::CreateList:
- //
- // Create an empty descriptor list or AERecord with factored data.
- //
- // n.b. It is better to call MakeList, MakeEmptyList or MakeAERecord rather than
- // using TDescriptor::CreateList directly.
- //----------------------------------------------------------------------------------------
- void TDescriptor::CreateList(Boolean isRecord, Ptr factoringPtr, Size factoredSize)
- {
- FailErr(AECreateList(factoringPtr, factoredSize, isRecord, *this));
- } // TDescriptor::CreateList
-
- //----------------------------------------------------------------------------------------
- // TDescriptor::MakeNull:
- //----------------------------------------------------------------------------------------
- void TDescriptor::MakeNull()
- {
- this->AdoptHandle(typeNull, nil);
- } // TDescriptor::MakeNull
-
- //----------------------------------------------------------------------------------------
- // TDescriptor::AdoptHandle:
- //
- // Assign some data and a type directly to the descriptor
- //----------------------------------------------------------------------------------------
- void TDescriptor::AdoptHandle(DescType dataType, Handle dataHandle)
- {
- fDescriptorType = dataType;
- fDataHandle = dataHandle;
- } // TDescriptor::AdoptHandle
-
- //----------------------------------------------------------------------------------------
- // TDescriptor::CopyData:
- //----------------------------------------------------------------------------------------
- void TDescriptor::CopyData(const DescType typeCode, const Ptr data, const Size length)
- {
- FailErr(AECreateDesc(typeCode, data, length, *this));
- } // TDescriptor::CopyData
-
- //----------------------------------------------------------------------------------------
- // TDescriptor::MakeBoolean:
- //----------------------------------------------------------------------------------------
- void TDescriptor::MakeBoolean(const Boolean data)
- {
- this->CopyData(typeBoolean, (Ptr)&data, sizeof(Boolean));
- } // TDescriptor::MakeBoolean
-
- //----------------------------------------------------------------------------------------
- // TDescriptor::MakeLong:
- //----------------------------------------------------------------------------------------
- void TDescriptor::MakeLong(const long data)
- {
- this->CopyData(typeLongInteger, (Ptr)&data, sizeof(long));
- } // TDescriptor::MakeLong
-
- //----------------------------------------------------------------------------------------
- // TDescriptor::MakeUnsignedLong:
- //----------------------------------------------------------------------------------------
- void TDescriptor::MakeUnsignedLong(const unsigned long data)
- {
- this->CopyData(typeMagnitude, (Ptr)&data, sizeof(unsigned long));
- } // TDescriptor::MakeUnsignedLong
-
- //----------------------------------------------------------------------------------------
- // TDescriptor::MakeEnumeration:
- //----------------------------------------------------------------------------------------
- void TDescriptor::MakeEnumeration(const DescType enumeration)
- {
- this->CopyData(typeEnumeration, (Ptr)&enumeration, sizeof(enumeration));
- } // TDescriptor::MakeEnumeration
-
- //----------------------------------------------------------------------------------------
- // TDescriptor::MakeDescType:
- //----------------------------------------------------------------------------------------
- void TDescriptor::MakeDescType(const DescType data)
- {
- this->CopyData(typeType, (Ptr)&data, sizeof(DescType));
- } // TDescriptor::MakeDescType
-
- //----------------------------------------------------------------------------------------
- // TDescriptor::MakeKeyword:
- //----------------------------------------------------------------------------------------
- void TDescriptor::MakeKeyword(const AEKeyword theKeyword)
- {
- this->CopyData(typeKeyword, (Ptr)&theKeyword, sizeof(AEKeyword));
- } // TDescriptor::MakeKeyword
-
- //----------------------------------------------------------------------------------------
- // TDescriptor::MakeOrdinal:
- //----------------------------------------------------------------------------------------
- void TDescriptor::MakeOrdinal(const DescType data)
- {
- this->CopyData(typeAbsoluteOrdinal, (Ptr)&data, sizeof(DescType));
- } // TDescriptor::MakeOrdinal
-
- //----------------------------------------------------------------------------------------
- // TDescriptor::MakeTypeOrInteger:
- //
- // This is useful for debugging; it makes a 'type' if the data
- // appears to consist of printable characters (e.g. 'ABCD'), but
- // otherwise it makes an integer (e.g. -12).
- //----------------------------------------------------------------------------------------
- void TDescriptor::MakeTypeOrInteger(const DescType data)
- {
- if(((data >= 'A000') && (data <= 'Zzzz')) || ((data >= 'a000') && (data <= 'zzzz')))
- this->MakeDescType(data);
- else
- this->MakeLong(data);
- } // TDescriptor::MakeTypeOrInteger
-
- //----------------------------------------------------------------------------------------
- // TDescriptor::MakePoint:
- //----------------------------------------------------------------------------------------
- void TDescriptor::MakePoint(const Point& thePoint)
- {
- this->CopyData(typeQDPoint, (Ptr)&thePoint, sizeof(Point));
- } // TDescriptor::MakePoint
-
- //----------------------------------------------------------------------------------------
- // TDescriptor::MakePoint:
- //----------------------------------------------------------------------------------------
- void TDescriptor::MakePoint(const short h, const short v)
- {
- Point thePoint;
-
- thePoint.v = v;
- thePoint.h = h;
- this->MakePoint(thePoint);
- } // TDescriptor::MakePoint
-
- //----------------------------------------------------------------------------------------
- // TDescriptor::MakeRect:
- //----------------------------------------------------------------------------------------
- void TDescriptor::MakeRect(const Rect& theRect)
- {
- this->CopyData(typeQDRectangle, (Ptr)&theRect, sizeof(Rect));
- } // TDescriptor::MakeRect
-
- //----------------------------------------------------------------------------------------
- // TDescriptor::MakeString:
- //----------------------------------------------------------------------------------------
- void TDescriptor::MakeString(Str255 data)
- {
- Size length = data[0];
-
- this->CopyData(typeChar, (Ptr)&data[1], length);
- } // TDescriptor::MakeString
-
- //----------------------------------------------------------------------------------------
- // TDescriptor::MakeDateTimeRec:
- //----------------------------------------------------------------------------------------
- void TDescriptor::MakeDateTimeRec(const DateTimeRec dateTime)
- {
- this->CopyData(typeDateTimeRec, (Ptr)&dateTime, sizeof(DateTimeRec));
- } // TDescriptor::MakeDateTimeRec
-
- //----------------------------------------------------------------------------------------
- // TDescriptor::MakeDateTimeRec:
- //----------------------------------------------------------------------------------------
- void TDescriptor::MakeDateTimeRec(const long secsSince1904)
- {
- DateTimeRec dateTime;
-
- //
- // Let the OSUtilities do the hard work of converting seconds
- // since 1904 into a DateTimeRec
- //
- Secs2Date(secsSince1904,&dateTime);
- this->MakeDateTimeRec(dateTime);
- } // TDescriptor::MakeDateTimeRec
-
- //----------------------------------------------------------------------------------------
- // TDescriptor::MakeLongDateTimeRec:
- //----------------------------------------------------------------------------------------
- void TDescriptor::MakeLongDateTimeRec(const LongDateRec dateTime)
- {
- this->CopyData(typeLongDateTimeRec, (Ptr)&dateTime, sizeof(LongDateRec));
- } // TDescriptor::MakeLongDateTimeRec
-
- //----------------------------------------------------------------------------------------
- // TDescriptor::MakeLongDateTimeRec:
- //----------------------------------------------------------------------------------------
- void TDescriptor::MakeLongDateTimeRec(const DateTimeRec dateTime)
- {
- LongDateRec longDateTime;
-
- longDateTime.od.eraAlt = 0;
- longDateTime.od.oldDate = dateTime;
-
- this->MakeLongDateTimeRec(longDateTime);
- } // TDescriptor::MakeLongDateTimeRec
-
- //----------------------------------------------------------------------------------------
- // TDescriptor::MakeLongDateTimeRec:
- //----------------------------------------------------------------------------------------
- void TDescriptor::MakeLongDateTimeRec(LongDateTime lsecs)
- {
- LongDateRec longDateTime;
-
- LongSecs2Date(&lsecs, &longDateTime);
- this->MakeLongDateTimeRec(longDateTime);
- } // TDescriptor::MakeLongDateTimeRec
-
- //----------------------------------------------------------------------------------------
- // TDescriptor::MakeLongDateTime:
- //----------------------------------------------------------------------------------------
- void TDescriptor::MakeLongDateTime(const LongDateTime lsecs)
- {
- this->CopyData(typeLongDateTime, (Ptr)&lsecs, sizeof(LongDateTime));
- } // TDescriptor::MakeLongDateTime
-
- //----------------------------------------------------------------------------------------
- // TDescriptor::MakeFSS:
- //----------------------------------------------------------------------------------------
- void TDescriptor::MakeFSS(const FSSpec& spec)
- {
- this->CopyData(typeFSS, (Ptr)&spec, sizeof(FSSpec));
- } // TDescriptor::MakeFSS
-
- //----------------------------------------------------------------------------------------
- // TDescriptor::AdoptAlias:
- //
- // Takes the provided alias handle and keeps it forever.
- //----------------------------------------------------------------------------------------
- void TDescriptor::AdoptAlias(Handle alias)
- {
- this->AdoptHandle(typeAlias, alias);
- } // TDescriptor::AdoptAlias
-
- //----------------------------------------------------------------------------------------
- // TDescriptor::MakeAlias:
- //
- // You would think that someone would have spent five minutes to make a coercion
- // handler that goes from FSSpecs to Alias records, but nooooooo...
- //----------------------------------------------------------------------------------------
- void TDescriptor::MakeAlias(FSSpec& spec)
- {
- AliasHandle alias;
-
- FailErr(NewAliasMinimal(&spec, &alias));
- this->AdoptAlias((Handle)alias);
- } // TDescriptor::MakeAlias
-
- //----------------------------------------------------------------------------------------
- // TDescriptor::MakeProcessSerialNumber:
- //----------------------------------------------------------------------------------------
- void TDescriptor::MakeProcessSerialNumber(ProcessSerialNumber psn)
- {
- this->CopyData(typeProcessSerialNumber, (Ptr)&psn, sizeof(ProcessSerialNumber));
- } // TDescriptor::MakeProcessSerialNumber
-
- //----------------------------------------------------------------------------------------
- // TDescriptor::MakeObjectSpecifier:
- //----------------------------------------------------------------------------------------
- void TDescriptor::MakeObjectSpecifier(DescType desiredClass, TDescriptor container, DescType keyForm, TDescriptor keyData, Boolean disposeInputs)
- {
- FailErr(CreateObjSpecifier(desiredClass,container,keyForm,keyData,disposeInputs,*this));
- } // TDescriptor::MakeObjectSpecifier
-
- //----------------------------------------------------------------------------------------
- // TDescriptor::MakeCompDescriptor:
- //----------------------------------------------------------------------------------------
- void TDescriptor::MakeCompDescriptor(DescType comparisonOperator, DescType propertyIdentifier, TDescriptor compareWith, Boolean disposeInputs)
- {
- TDescriptor operand1;
- TDescriptor propertyIDDesc;
- TDescriptor objectBeingExamined;
-
- //
- // 'objectBeingExamined' is a special object specifier that only
- // has meaning in the context of a comparison descriptor
- //
- objectBeingExamined.AdoptHandle(typeObjectBeingExamined,nil);
-
- //
- // Operand1 is "fPropertyIdentifier of (object being examined)"
- //
- propertyIDDesc.MakeDescType(propertyIdentifier);
- operand1.MakeObjectSpecifier(cProperty, objectBeingExamined, formPropertyID, propertyIDDesc, true);
-
- //
- // Make a compDescriptor of operand1 compared with (fComparisonOperator) fCompareWith
- //
- CreateCompDescriptor(comparisonOperator, operand1, compareWith, disposeInputs, *this);
- } // TDescriptor::MakeCompDescriptor
-
- //----------------------------------------------------------------------------------------
- // TDescriptor::GetBlock:
- //----------------------------------------------------------------------------------------
- void TDescriptor::GetBlock(Ptr data, Size length, DescType desiredType) const
- {
- if(this->DataHandleIsNil())
- FailErr(errAECantSupplyType);
-
- if(this->DescriptorType() != desiredType)
- {
- TDescriptor coerceData;
-
- coerceData = this->Coerce(desiredType);
- coerceData.GetBlock(data,length,desiredType);
- coerceData.Dispose();
- }
- else
- {
- //
- // It would be just wrong to have a situation where a
- // descriptor is of the requested type, but not of the
- // requested length. This method is only usable for
- // fixed-size blocks
- //
- if(GetHandleSize(fDataHandle) != length)
- {
- FailErr(errAECorruptData);
- }
-
- BlockMove(*fDataHandle, data, length);
- }
- } // TDescriptor::GetBlock
-
- //----------------------------------------------------------------------------------------
- // TDescriptor::GetLong:
- //----------------------------------------------------------------------------------------
- long TDescriptor::GetLong() const
- {
- long result = 0;
-
- this->GetBlock((Ptr)&result, sizeof(long), typeLongInteger);
-
- return result;
- } // TDescriptor::GetLong
-
- //----------------------------------------------------------------------------------------
- // TDescriptor::GetBoolean:
- //----------------------------------------------------------------------------------------
- Boolean TDescriptor::GetBoolean() const
- {
- Boolean result = 0;
-
- this->GetBlock((Ptr)&result, sizeof(Boolean), typeBoolean);
-
- return result;
- } // TDescriptor::GetBoolean
-
- //----------------------------------------------------------------------------------------
- // TDescriptor::GetDescType:
- //----------------------------------------------------------------------------------------
- DescType TDescriptor::GetDescType() const
- {
- DescType result = 0;
-
- this->GetBlock((Ptr)&result, sizeof(DescType), typeType);
-
- return result;
- } // TDescriptor::GetDescType
-
- //----------------------------------------------------------------------------------------
- // TDescriptor::GetKeyword:
- //----------------------------------------------------------------------------------------
- AEKeyword TDescriptor::GetKeyword() const
- {
- AEKeyword result = 0;
-
- this->GetBlock((Ptr)&result, sizeof(AEKeyword), typeKeyword);
-
- return result;
- } // TDescriptor::GetKeyword
-
- //----------------------------------------------------------------------------------------
- // TDescriptor::GetEnumeration:
- //----------------------------------------------------------------------------------------
- DescType TDescriptor::GetEnumeration() const
- {
- DescType result = 0;
-
- this->GetBlock((Ptr)&result, sizeof(DescType), typeEnumeration);
-
- return result;
- } // TDescriptor::GetEnumeration
-
- //----------------------------------------------------------------------------------------
- // TDescriptor::GetOrdinal:
- //----------------------------------------------------------------------------------------
- DescType TDescriptor::GetOrdinal() const
- {
- DescType result = 0;
-
- this->GetBlock((Ptr)&result, sizeof(DescType), typeAbsoluteOrdinal);
-
- return result;
- } // TDescriptor::GetOrdinal
-
- //----------------------------------------------------------------------------------------
- // TDescriptor::GetPoint:
- //----------------------------------------------------------------------------------------
- Point TDescriptor::GetPoint() const
- {
- Point result;
-
- this->GetBlock((Ptr)&result, sizeof(Point), typeQDPoint);
-
- return result;
- } // TDescriptor::GetPoint
-
- //----------------------------------------------------------------------------------------
- // TDescriptor::GetRect:
- //----------------------------------------------------------------------------------------
- Rect TDescriptor::GetRect() const
- {
- Rect result;
-
- this->GetBlock((Ptr)&result, sizeof(Rect), typeQDRectangle);
-
- return result;
- } // TDescriptor::GetRect
-
- //----------------------------------------------------------------------------------------
- // TDescriptor::GetString:
- //----------------------------------------------------------------------------------------
- void TDescriptor::GetString(Str255 result) const
- {
- result[0] = 0;
-
- if(this->DataHandleIsNil())
- FailErr(errAECantSupplyType);
-
- if(this->DescriptorType() == typeChar)
- {
- Size length = GetHandleSize(fDataHandle);
- if(length > 255)
- length = 255;
- BlockMove(*fDataHandle, (Ptr)&result[1], length);
- result[0] = (unsigned char) length;
- }
- else
- {
- TDescriptor makeDataString;
-
- makeDataString = this->Coerce(typeChar);
- ASSERT(makeDataString.DescriptorType() == typeChar);
- makeDataString.GetString(result);
- makeDataString.Dispose();
- }
- } // TDescriptor::GetString
-
- //----------------------------------------------------------------------------------------
- // TDescriptor::GetDateTimeRec:
- //----------------------------------------------------------------------------------------
- DateTimeRec TDescriptor::GetDateTimeRec() const
- {
- DateTimeRec dateTime;
-
- //
- // We'll do our own coercion from typeLongInteger, if necessary.
- // We should really have a coercion handler for this
- //
- if(this->DescriptorType() == typeLongInteger)
- {
- long secsSince1904 = this->GetLong();
- Secs2Date(secsSince1904,&dateTime);
- }
- else
- {
- //
- // Get the time date rec
- //
- this->GetBlock( (Ptr)&dateTime, sizeof(DateTimeRec), typeDateTimeRec);
- }
-
- return dateTime;
- } // TDescriptor::GetDateTimeRec
-
- //----------------------------------------------------------------------------------------
- // TDescriptor::GetFSS:
- //----------------------------------------------------------------------------------------
- void TDescriptor::GetFSS(FSSpec& spec) const
- {
- this->GetBlock((Ptr)&spec, sizeof(FSSpec), typeFSS);
- } // TDescriptor::GetFSS
-
- //----------------------------------------------------------------------------------------
- // InterpretCompareResult:
- //
- // Given two keys and a comparison opperator, this function determines if
- // the comparison between key2 and key1 is true or false. key1 and key2 should
- // be either two long integers representing the various values of the two descriptors
- // being compared, or key1 may be set to 0 and key2 set to -1 (key2 < key1), 0
- // (key1 == key2) or 1 (key2 > key1).
- //
- // This function is used by GeneralCompare, which is used by TDescriptor::Compare
- //----------------------------------------------------------------------------------------
- Boolean InterpretCompareResult(DescType comparisonOperator, long key1, long key2 )
- {
- switch(comparisonOperator)
- {
- case kAEEquals:
- {
- return key1 == key2;
- }
-
- case kASNotEqual:
- {
- return key1 != key2;
- }
-
- case kAEGreaterThan:
- {
- return key1 > key2;
- }
-
- case kAEGreaterThanEquals:
- {
- return key1 >= key2;
- }
-
- case kAELessThan:
- {
- return key1 < key2;
- }
-
- case kAELessThanEquals:
- {
- return key1 <= key2;
- }
-
- //
- // ••• Perhaps we should fail if we don't recognize the comparisonOperator
- //
- default:
- {
- return false;
- }
- }
- } // InterpretCompareResult
-
- //----------------------------------------------------------------------------------------
- // GeneralCompare:
- //
- // This is a general comparison routine that works on streams of bytes. It is assumed
- // that the data being compared follows the same ordering rules as strings. The
- // 'caseSensitive' flag should always be true for non-string objects, of course.
- //----------------------------------------------------------------------------------------
- Boolean GeneralCompare(DescType comparisonOperator, Ptr data, Size length, Ptr compareWith, Size comparisonLength, Boolean caseSensitive)
- {
- Boolean comparisonResult = false;
- long i = 0;
-
- switch(comparisonOperator)
- {
- case kAEEquals:
- case kASNotEqual:
- case kAEGreaterThan:
- case kAEGreaterThanEquals:
- case kAELessThan:
- case kASLessThanOrEqual:
- {
- short intermediateResult = 0;
- Size max = (length < comparisonLength ? length : comparisonLength);
-
- //
- // We have a little bit of code duplication here
- // to make the code run a little faster
- //
- if(caseSensitive)
- {
- for(i=0; i < max; ++i)
- {
- if(*((unsigned char*)compareWith) > *((unsigned char*)data))
- {
- intermediateResult = 1;
- break;
- }
- else if(*((unsigned char*)compareWith) < *((unsigned char*)data))
- {
- intermediateResult = -1;
- break;
- }
- ++compareWith;
- ++data;
- }
- }
- else
- {
- for(i=0; i < max; ++i)
- {
- unsigned char compareWithChar = *((unsigned char*)compareWith);
- unsigned char dataChar = *((unsigned char*)data);
-
- if((compareWithChar >= 'a') && (compareWithChar <= 'z'))
- compareWithChar = compareWithChar - 'a' + 'A';
- if((dataChar >= 'a') && (dataChar <= 'z'))
- dataChar = dataChar - 'a' + 'A';
-
- if(compareWithChar > dataChar)
- {
- intermediateResult = 1;
- break;
- }
- else if(compareWithChar < dataChar)
- {
- intermediateResult = -1;
- break;
- }
- ++compareWith;
- ++data;
- }
- }
-
- if(intermediateResult == 0)
- intermediateResult = (comparisonLength > length) - (comparisonLength < length);
-
- comparisonResult = InterpretCompareResult(comparisonOperator,0,intermediateResult);
-
- break;
- }
-
- case kAEBeginsWith:
- {
- comparisonResult = GeneralCompare(kAEEquals, data, comparisonLength, compareWith, comparisonLength,caseSensitive);
- break;
- }
-
- case kAEEndsWith:
- {
- i = (length - comparisonLength);
- if(i >= 0)
- comparisonResult = GeneralCompare(kAEEquals, data + i, comparisonLength, compareWith, comparisonLength,caseSensitive);
- break;
- }
-
- case kAEContains:
- {
- for(i=0;i<=length - comparisonLength;++i)
- {
- if(GeneralCompare(kAEEquals, data + i, comparisonLength, compareWith, comparisonLength,caseSensitive))
- {
- comparisonResult = true;
- break;
- }
- }
-
- break;
- }
-
- default:
- {
- comparisonResult = false;
- }
- }
-
- return comparisonResult;
- } // GeneralCompare
-
-
- //----------------------------------------------------------------------------------------
- // StringContains:
- //----------------------------------------------------------------------------------------
- /*Boolean StringContains(Str255 thisString, Str255 withString)
- {
- unsigned char thisSize = (unsigned char)thisString[0];
- unsigned char withSize = (unsigned char)withString[0];
-
- if ((thisSize == 0) || (withSize > thisSize)) // quick check
- return false;
-
- Boolean b = false;
- unsigned char* a = &thisString[0];
- unsigned char* last = a + thisSize - withSize + 1;
- do
- {
- b = IUMagIDString(Ptr(++a), Ptr(withString[1]), withSize, withSize);
- }
- while (b && (a < last));
-
- return (b == false);
- } // StringContains */
-
- //----------------------------------------------------------------------------------------
- // TDescriptor::Compare:
- //----------------------------------------------------------------------------------------
- Boolean TDescriptor::Compare(DescType comparisonOperator, Str255 withString) const
- {
- Str255 thisString;
- Size thisSize;
- Size withSize;
- Boolean compareResult = false;
-
- //
- // Fetch a copy of 'thisString' (which we will freely destroy later)
- //
- this->GetString(thisString);
- thisSize = (unsigned char)thisString[0];
- withSize = (unsigned char)withString[0];
-
- switch(comparisonOperator)
- {
- //
- // Check to see if we can find the string anywhere inside
- //
- case kAEContains:
- {
- long i;
-
- unsigned char* a = &thisString[0];
- for(i=0;i<thisSize - withSize + 1;++i)
- {
- *a = (unsigned char)withSize;
- compareResult = (IUEqualString(a, withString) == 0);
- if(compareResult == true)
- break;
- ++a;
- }
- }
- break;
-
- //
- // Relational tests are easy: use IUCompString
- //
- case kAEGreaterThan:
- case kAEGreaterThanEquals:
- case kAELessThan:
- case kASLessThanOrEqual:
- {
- compareResult = InterpretCompareResult(comparisonOperator, IUCompString(thisString, withString), 0);
- }
- break;
-
- //
- // For AEEndsWith, move the end of the string down to
- // the beginning of the string, then fall through to
- // the 'begins with' case
- //
- // International allert: this could clip a two-byte
- // character in half, but doing so probably won't cause
- // a problem, since we are looking for exact matches.
- //
- case kAEEndsWith:
- {
- if(withSize <= thisSize)
- BlockMove((Ptr)&thisString[thisSize - withSize + 1],(Ptr)&thisString[1],withSize);
- }
- // !!! fall through
-
- //
- // For kAEBeginsWith, set the length of the 'thisString'
- // to the length of the 'withString' and do an equality test
- //
- // International allert: this could clip a two-byte
- // character in half, but doing so probably won't cause
- // a problem, since we are looking for exact matches.
- //
- case kAEBeginsWith:
- {
- thisString[0] = (unsigned char)withSize;
- }
- // !!! fall through...
-
- //
- // kAEEquals and kASNotEqual must come immediately after
- // begins with and ends with
- //
- case kAEEquals:
- case kASNotEqual:
- {
- compareResult = (IUEqualString(thisString, withString) == 0);
- if(comparisonOperator == kASNotEqual)
- compareResult = !compareResult;
- }
- break;
-
- //
- // Shouldn't ever get here...
- //
- default:
- {
- compareResult = GeneralCompare(comparisonOperator,(Ptr)&thisString[1],thisSize,(Ptr)&withString[1],withSize,false);
- }
- break;
- }
-
- return compareResult;
- } // TDescriptor::Compare
-
- //----------------------------------------------------------------------------------------
- // TDescriptor::Compare:
- //
- // Compare two descriptors. ComparisonOperator should be one of the following:
- //
- // kAEEquals, kASNotEqual, kAEGreaterThan, kAEGreaterThanEquals, kAELessThan,
- // kASLessThanOrEqual, kAEBeginsWith, kAEEndsWith, or kAEContains
- //----------------------------------------------------------------------------------------
- Boolean TDescriptor::Compare(DescType comparisonOperator, TDescriptor& compareWith) const
- {
- Boolean compareResult = false;
-
- //
- // It might be nice to try to do a type coercion here, but for now
- // we only compare descriptors of the same type
- //
- if(this->DescriptorType() != compareWith.DescriptorType())
- FailErr(errAEEventNotHandled);
-
- switch(this->DescriptorType())
- {
- case typeChar:
- {
- Str255 withString;
-
- compareWith.GetString(withString);
- compareResult = this->Compare(comparisonOperator, withString);
-
- break;
- }
- break;
-
- //
- // We convert DateTimeRecs into integers for comparison so that
- // someone can supply "the 300th day of January", and it will compare
- // as being larger than "the 2nd day of February".
- //
- // Begins with, ends with and contains are meaningless for dates, though.
- //
- case typeLongInteger:
- case typeDateTimeRec:
- {
- compareResult = InterpretCompareResult(comparisonOperator, this->GetLong(), compareWith.GetLong() );
- }
- break;
-
- //
- // If we don't know what type this is, we'll do our best
- // to do a generic comparison. This can result in some
- // very stupid comparisons, but that's life.
- //
- default:
- {
- Handle withHandle = compareWith.DataHandle();
- short thisState;
- short withState;
- Size thisSize;
- Size withSize;
-
- thisState = HGetState(fDataHandle);
- withState = HGetState(withHandle);
- thisSize = GetHandleSize(fDataHandle);
- withSize = GetHandleSize(withHandle);
-
- compareResult = GeneralCompare(comparisonOperator,(Ptr)*fDataHandle,thisSize,(Ptr)*withHandle,withSize,true);
-
- HSetState(fDataHandle,thisState);
- HSetState(withHandle,withState);
- }
- break;
- }
-
- return compareResult;
- } // TDescriptor::Compare
-
- //========================================================================================
- // CLASS TDescriptorLoop
- //
- // The class TDescriptorLoop is used by the macro FOREACHDESCRIPTOR. Note that the
- // descriptor returned by "Next" is a copy that must be disposed of by the programmer.
- //
- // We could have TDescriptorLoop keep track of the descriptor it created, and have it
- // dispose it when done. This would necessitate an 'orphan' method, though, in case
- // someone else wanted to adopt the descriptor.
- //========================================================================================
-
- //----------------------------------------------------------------------------------------
- // TDescriptorLoop::Next:
- //
- // If 'key' is not nil, it is filled in with the keyword from the i'th item of the
- // list (if the list is a record)
- //
- // If 'dataHandle' is not nil, it is filled in with the data handle from the i'th
- // item of the list. This is only done to be nice to the FOREACHTOKEN macro.
- //----------------------------------------------------------------------------------------
- Boolean TDescriptorLoop::Next(TDescriptor& d, AEKeyword* key, Handle* dataHandle)
- {
- Boolean moreToDo = false;
-
- //
- // Set up on the first time through the loop
- //
- if(fIndex == 0)
- {
- fCount = fDescriptorList->CountItems();
- if(d.IsNullDescriptor() == false)
- {
- DebugStr("\pTDescriptorLoop::Next: 'd' was not null on first iteration!");
- FailErr(errAEEventFailed);
- }
- }
-
- //
- // Advance to the next item in the list...
- //
- fIndex++;
-
- //
- // Dispose of the 'd' from last time through the loop
- //
- d.Dispose();
-
- //
- // Are there still items in the list?
- //
- if (fIndex <= fCount)
- {
- //
- // At this point, we could check to see if 'fDescriptorList' actually
- // points to something that is _not_ a list; if so, we coule return a
- // _reference_ to the single object, and set a field that indicates that
- // 'd' is a reference, and should not be disposed next time through the
- // loop. The reason we do not do this is that 'd' will be disposed by
- // the client code if there is a failure, and there is no good way for
- // the client to know if d is a reference or not. We could remember
- // what 'd' was and clean it up in our destructor, but failures can
- // cause our TDescriptorLoop object to be orphaned without ever being
- // destructed.
- //
- d = fDescriptorList->GetNthDescriptor(fIndex, typeWildCard, key);
-
- moreToDo = true;
- }
- //
- // No more items, clean up
- //
- else
- {
- if(key != nil)
- *key = typeNull;
- d.MakeNull();
- }
-
- //
- // Fill in the 'dataHandle' parameter if it was passed in.
- // (We only do this to make life easy for the FOREACHTOKEN macro)
- //
- if(dataHandle != nil)
- *dataHandle = d.DataHandle();
-
- return moreToDo;
- } // TDescriptorLoop::Next
-
-
- //----------------------------------------------------------------------------------------
- // TDescriptor::MakeEmptyList:
- //
- // Make an empty descriptor list. It is usually not necessary to make an empty list,
- // because all of the TDescriptor routines will interpret null descriptors as
- // empty lists. Sometimes it is necessary to return an empty list as the result of
- // an AppleEvent handler, though, and in this case a null descriptor is _not_ equivalent.
- //
- // By default, include no factored data and make an AEList.
- //----------------------------------------------------------------------------------------
- void TDescriptor::MakeEmptyList()
- {
- this->CreateList(kMakeAEList);
- } // TDescriptor::MakeEmptyList
-
- //----------------------------------------------------------------------------------------
- // TDescriptor::MakeList:
- //
- // If this descriptor is null, an empty list is created. If this descriptor is not
- // empty, then a list is created and this descriptor is placed inside it. If this
- // descriptor is already a list, then no action is taken.
- //
- // ••• DANGER: Does a coerce-in-place!
- //----------------------------------------------------------------------------------------
- void TDescriptor::MakeList()
- {
- if(this->IsNullDescriptor())
- {
- this->CreateList();
- }
- else if(this->DescriptorType() != typeAEList)
- {
- this->CoerceInPlace(typeAEList);
- }
- } // TDescriptor::MakeList
-
- //----------------------------------------------------------------------------------------
- // TDescriptor::CountItems:
- //
- // Count the items in a descriptor list. If this descriptor is not of typeAEList, then it
- // only has one item, and if the descriptor is null, then it has no items.
- //----------------------------------------------------------------------------------------
- long TDescriptor::CountItems() const
- {
- long items = 1;
- if(this->IsNullDescriptor())
- items = 0;
- else if((this->DescriptorType() == typeAEList) || (this->DescriptorType() == typeAERecord))
- FailErr(AECountItems(*this, &items));
- return items;
- } // TDescriptor::CountItems
-
- //----------------------------------------------------------------------------------------
- // TDescriptor::GetNthDescriptor:
- //
- // Get the indexed descriptor from an event. This method will fail if given an index
- // less than one or greater than the count returned by TDescriptor::CountItems.
- // The descriptor returned is _always_ a copy that must be disposed of with
- // TDescriptor::Dispose.
- //----------------------------------------------------------------------------------------
- TDescriptor TDescriptor::GetNthDescriptor(long index, DescType desiredType, AEKeyword* key) const
- {
- TDescriptor descriptor;
- AEKeyword ignoreKey;
-
- if(key == nil)
- key = &ignoreKey;
-
- //
- // We can "GetNthDescriptor" on an item that is not of typeAEList
- // if the index is one; we do this by cloning ourself
- // (n.b. AERecords are also lists)
- //
- if((DescriptorType() != typeAEList) && (DescriptorType() != typeAERecord))
- {
- if(index != 1)
- FailErr(-1); // ••• index out of range
-
- *key = typeWildCard;
- descriptor = this->Clone();
- }
- else
- {
- FailErr(AEGetNthDesc(*this, index, desiredType, key, descriptor));
- }
-
- return descriptor;
- } // TDescriptor::GetNthDescriptor
-
- //----------------------------------------------------------------------------------------
- // TDescriptor::AddDescriptor:
- //
- // Add data to a descriptor list at a specified index, replacing any item already stored
- // at that position.
- //----------------------------------------------------------------------------------------
- void TDescriptor::AddDescriptor(long index, TDescriptor& data)
- {
- //
- // If the list is completely empty, just put the data directly into
- // this descriptor (don't make a list)
- //
- if(this->IsNullDescriptor())
- {
- this->CopyDesc(data);
- }
- else
- {
- // If we're not a list yet, we'd better make ourselves one now.
- if(this->DescriptorType() != typeAEList)
- this->MakeList();
- FailErr(AEPutDesc(*this, index, data));
- }
- } // TDescriptor::AddDescriptor
-
- //----------------------------------------------------------------------------------------
- // TDescriptor::AddDescriptor:
- //
- // Add data to a descriptor list at the end of the list
- //----------------------------------------------------------------------------------------
- void TDescriptor::AddDescriptor(TDescriptor& data)
- {
- this->AddDescriptor(0,data);
- } // TDescriptor::AddDescriptor
-
- //----------------------------------------------------------------------------------------
- // TDescriptor::AddData:
- //----------------------------------------------------------------------------------------
- void TDescriptor::AddData(long index, DescType descType, Ptr data, Size length)
- {
- //
- // If the list is completely empty, we'd better make an empty list
- // (the type coercion from null to typeAEList probably works,
- // but I have not tested it yet; the following two lines may
- // be superfluous)
- //
- if(this->IsNullDescriptor())
- this->MakeEmptyList();
-
- //
- // If we're not a list yet, we'd better make ourselves one now.
- //
- if(this->DescriptorType() != typeAEList)
- this->CoerceInPlace(typeAEList);
-
- //
- // Put the data into the list
- //
- FailErr(AEPutPtr(*this,index,descType,data,length));
- } // TDescriptor::AddData
-
- //----------------------------------------------------------------------------------------
- // TDescriptor::AddData:
- //----------------------------------------------------------------------------------------
- void TDescriptor::AddData(DescType descType, Ptr data, Size length)
- {
- this->AddData(0,descType,data,length);
- } // TDescriptor::AddData
-
- //----------------------------------------------------------------------------------------
- // TDescriptor::AddLong:
- //----------------------------------------------------------------------------------------
- void TDescriptor::AddLong(long number)
- {
- this->AddData(typeLongInteger,(Ptr)&number,sizeof(long));
- } // TDescriptor::AddLong
-
- //----------------------------------------------------------------------------------------
- // TDescriptor::AddType:
- //----------------------------------------------------------------------------------------
- void TDescriptor::AddType(DescType descType)
- {
- this->AddData(typeType,(Ptr)&descType,sizeof(DescType));
- } // TDescriptor::AddType
-
- //----------------------------------------------------------------------------------------
- // TDescriptor::AppendList:
- //
- // Append a list onto the end of this one. The list passed in may be a null descriptor
- // or a single item as well as a list.
- //----------------------------------------------------------------------------------------
- void TDescriptor::AppendList(const TDescriptor& list)
- {
- TDescriptor descriptor;
- OSErr err = noErr;
-
- //
- // If this descriptor is a null descriptor, then we just want
- // to copy the incoming list.
- //
- // In the past we did not do this check, which resulted in
- // the unfortunate side effect of converting a single-item
- // list into a single (non-list) descriptor whenever said
- // list was 'AppendList'ed into an empty list. While this
- // may be more efficient, it really hosed us over in the case
- // of GetData on the selection property, which is SUPPOSED
- // to return a single-item list (as opposed to a single
- // descriptor) if there is only one item in the list. (This
- // is quite different from most other objects, which are
- // supposed to return single descriptors instead of single-
- // item lists whenever there is only one object in the result.)
- //
- if(this->IsNullDescriptor())
- {
- this->CopyDesc(list);
- }
- else if(list.IsNullDescriptor() == false)
- {
- Try
- {
- FOREACHDESCRIPTOR(&list, descriptor)
- {
- this->AddDescriptor(descriptor);
- }
- }
- Catch(err)
- {
- descriptor.Dispose();
- Throw(err);
- }
- }
- } // TDescriptor::AppendList
-
- //----------------------------------------------------------------------------------------
- // TDescriptor::AdoptList:
- //----------------------------------------------------------------------------------------
- void TDescriptor::AdoptList(TDescriptor* list)
- {
- if(this->IsNullDescriptor())
- {
- this->AdoptDesc(*list);
- }
- else
- {
- this->AppendList(*list);
- list->Dispose();
- }
- } // TDescriptor::AdoptList
-
- //----------------------------------------------------------------------------------------
- // TDescriptor::MakeAERecord:
- //
- // CreateList creates both AERecords and AELists.
- //----------------------------------------------------------------------------------------
- void TDescriptor::MakeAERecord()
- {
- this->CreateList(kMakeAERecord);
- } // TDescriptor::MakeAERecord
-
- //----------------------------------------------------------------------------------------
- // TDescriptor::GetDescriptor:
- //
- // Get the ae descriptor from the event. If the desired type is not specified, it
- // defaults to typeWildCard
- //----------------------------------------------------------------------------------------
- TDescriptor TDescriptor::GetDescriptor(AEKeyword key, DescType desiredType)
- {
- TDescriptor result;
-
- //
- // n.b. This object must be typeAERecord or typeAppleEvent, or this
- // call will fail. Other record-like descriptors (e.g. object specifiers)
- // cannot be passed to AEGetParamDesc.
- //
- FailErr(AEGetParamDesc(*this, key, desiredType, (AEDesc *) &result));
-
- return result;
- } // TDescriptor::GetDescriptor
-
- //----------------------------------------------------------------------------------------
- // TDescriptor::GetOptionalParameter:
- //
- // Like 'GetDescriptor, but returns a null descriptor if the specified parameter could not
- // be extracted.
- //----------------------------------------------------------------------------------------
- TDescriptor TDescriptor::GetOptionalParameter(AEKeyword key, DescType desiredType)
- {
- TDescriptor result;
- OSErr err = noErr;
-
- //
- // It's probably not necessary to call MakeNull if there is
- // an error, but we might as well be safe (paranoid?).
- //
- err = AEGetParamDesc(*this, key, desiredType, (AEDesc *) &result);
- if(err != noErr)
- result.MakeNull();
-
- return result;
- } // TDescriptor::GetOptionalParameter
-
- //----------------------------------------------------------------------------------------
- // TDescriptor::GetParameterPtr:
- //
- // Get the ae descriptor from the record
- //----------------------------------------------------------------------------------------
- void TDescriptor::GetParameterPtr(AEKeyword key, DescType desiredType, DescType *typeCode, Ptr dataPtr, Size maximumSize, Size *actualSize)
- {
- //
- // n.b. This object must be typeAERecord or typeAppleEvent, or this
- // call will fail. Other record-like descriptors (e.g. object specifiers)
- // cannot be passed to AEGetParamPtr.
- //
- FailErr(AEGetParamPtr(*this, key, desiredType, typeCode, dataPtr, maximumSize, actualSize));
- } // TDescriptor::GetParameterPtr
-
- //----------------------------------------------------------------------------------------
- // TDescriptor::GetLongParameter:
- //
- // Get the first longword of data from a parameter coerced to the specified type
- // (usually typeLongInteger)
- //----------------------------------------------------------------------------------------
- long TDescriptor::GetLongParameter(AEKeyword key, DescType desiredType)
- {
- long actualSize;
- DescType typeCode;
- long result = 0;
- GetParameterPtr(key, desiredType, &typeCode, (Ptr) &result, sizeof(long), &actualSize);
-
- return result;
- } // TDescriptor::GetLongParameter
-
- //----------------------------------------------------------------------------------------
- // TDescriptor::GetShortParameter:
- //
- // Get the first shortword of data from a parameter coerced to the specified type
- // (usually typeShortInteger)
- //----------------------------------------------------------------------------------------
- short TDescriptor::GetShortParameter(AEKeyword key, DescType desiredType)
- {
- long actualSize;
- DescType typeCode;
- short result = 0;
- GetParameterPtr(key, desiredType, &typeCode, (Ptr) &result, sizeof(short), &actualSize);
-
- return result;
- } // TDescriptor::GetShortParameter
-
- //----------------------------------------------------------------------------------------
- // TDescriptor::GetDirectObject:
- //
- // Get the direct object of the event
- //----------------------------------------------------------------------------------------
- TDescriptor TDescriptor::GetDirectObject()
- {
- return GetDescriptor(keyDirectObject);
- } // TDescriptor::GetDirectObject
-
- //----------------------------------------------------------------------------------------
- // TDescriptor::GetErrorCode:
- //
- // Get an error code
- //----------------------------------------------------------------------------------------
- long TDescriptor::GetErrorCode()
- {
- return GetLongParameter(keyErrorNumber);
- } // TDescriptor::GetErrorCode
-
- //----------------------------------------------------------------------------------------
- // TDescriptor::PutDescriptor:
- //
- // Put a TDescriptor into the event
- //----------------------------------------------------------------------------------------
- void TDescriptor::PutDescriptor(AEKeyword key, TDescriptor data)
- {
- FailErr(AEPutParamDesc(*this, key, data));
- } // TDescriptor::PutDescriptor
-
- //----------------------------------------------------------------------------------------
- // TDescriptor::PutParameterPtr:
- //
- // Create a descriptor from a block of data and insert it into the record
- //----------------------------------------------------------------------------------------
- void TDescriptor::PutParameterPtr(AEKeyword key, DescType typeCode, Ptr dataPtr, Size dataSize)
- {
- FailErr(AEPutParamPtr(*this, key, typeCode, dataPtr, dataSize));
- } // TDescriptor::PutParameterPtr
-
- //----------------------------------------------------------------------------------------
- // TDescriptor::PutParameterHandle:
- //----------------------------------------------------------------------------------------
- void TDescriptor::PutParameterHandle(AEKeyword key, DescType typeCode, Handle dataHandle)
- {
- short handleState;
- Size dataSize;
-
- //
- // Feature: if the dataHandle is nil, nothing is added to the AERecord.
- //
- if(dataHandle != nil)
- {
- handleState = HGetState(dataHandle);
- HLock(dataHandle);
- dataSize = GetHandleSize(dataHandle);
-
- this->PutParameterPtr(key,typeCode,*dataHandle,dataSize);
-
- HSetState(dataHandle,handleState);
- }
- } // TDescriptor::PutParameterHandle
-
- //----------------------------------------------------------------------------------------
- // TDescriptor::PutLongParameter:
- //
- // Put a long parameter (type specified)
- //----------------------------------------------------------------------------------------
- void TDescriptor::PutLongParameter(AEKeyword key, DescType typeCode, long data)
- {
- this->PutParameterPtr(key, typeCode, (Ptr) &data, sizeof(long));
- } // TDescriptor::PutLongParameter
-
- //----------------------------------------------------------------------------------------
- // TDescriptor::PutLongParameter:
- //
- // Put a long parameter (type is 'typeLongInteger', the most common case)
- //----------------------------------------------------------------------------------------
- void TDescriptor::PutLongParameter(AEKeyword key, long data)
- {
- this->PutLongParameter(key,typeLongInteger,data);
- } // TDescriptor::PutLongParameter
-
- //----------------------------------------------------------------------------------------
- // TDescriptor::PutShortParameter:
- //
- // Put a short parameter (type specified)
- //----------------------------------------------------------------------------------------
- void TDescriptor::PutShortParameter(AEKeyword key, DescType typeCode, short data)
- {
- this->PutParameterPtr(key, typeCode, (Ptr) &data, sizeof(short));
- } // TDescriptor::PutShortParameter
-
- //----------------------------------------------------------------------------------------
- // TDescriptor::PutShortParameter:
- //
- // Put a short parameter (type is 'typeShortInteger', the most common case)
- //----------------------------------------------------------------------------------------
- void TDescriptor::PutShortParameter(AEKeyword key, short data)
- {
- this->PutShortParameter(key,typeShortInteger,data);
- } // TDescriptor::PutShortParameter
-
- //----------------------------------------------------------------------------------------
- // TDescriptor::PutResult:
- //
- // Put the provided descriptor into the result parameter of this event. If the data
- // is a null descriptor, then put in an empty list instead.
- //----------------------------------------------------------------------------------------
- void TDescriptor::PutResult(TDescriptor data)
- {
- OSErr err = noErr;
-
- //
- // If there's nothing in the data, then insert an empty list.
- //
- if(data.IsNullDescriptor())
- {
- TDescriptor emptyList;
-
- Try
- {
- emptyList.MakeEmptyList();
- this->PutDescriptor(keyAEResult, emptyList);
- emptyList.Dispose();
- }
- Catch(err)
- {
- emptyList.Dispose();
- Throw(err);
- }
- }
- else
- {
- this->PutDescriptor(keyAEResult,data);
- }
- } // TDescriptor::PutResult
-
- //----------------------------------------------------------------------------------------
- // TDescriptor::PutErrorCode:
- //
- // Put an error code
- //----------------------------------------------------------------------------------------
- void TDescriptor::PutErrorCode(long theErr)
- {
- this->PutLongParameter(keyErrorNumber,theErr);
- } // TDescriptor::PutErrorCode
-
- //----------------------------------------------------------------------------------------
- // TDescriptor::Resolve:
- //----------------------------------------------------------------------------------------
- TTokenDescriptor TDescriptor::Resolve()
- {
- return TDescriptor::Resolve(fCallbackFlags);
- } // TDescriptor::Resolve
-
- //----------------------------------------------------------------------------------------
- // TDescriptor::Resolve:
- //
- // Resolves a list of object specifiers into a list of tokens. A null descriptor will
- // resolve to a token to the null container.
- //
- // n.b. AEResolve will return an error if you pass it a null descriptor; this is why
- // we include 'magic' checking for null descriptors here.
- //----------------------------------------------------------------------------------------
- TTokenDescriptor TDescriptor::Resolve(short callbackFlags)
- {
- TTokenDescriptor resolvedToken;
- TTokenDescriptor intermediate;
- TDescriptor descriptor;
-
- //
- // First: special checking for null descriptors
- //
- if(this->IsNullDescriptor())
- {
- resolvedToken = CreateNullContainerToken();
- }
- //
- // Next, process non-lists
- //
- else if(this->DescriptorType() != typeAEList)
- {
- //
- // If a pre-resolve proc was installed, then call it.
- //
- // The Scriptable Finder uses this for resolving token
- // types that AEResolve does not recognize (e.g. alias
- // records)
- //
- if(gPreResolveProc != nil)
- {
- resolvedToken = (*gPreResolveProc)(*this);
- }
-
- //
- // If the pre-resolve proc did not resolve the token,
- // then call AEResolve
- //
- if(resolvedToken.IsNullDescriptor())
- FailErr(AEResolve(*this, callbackFlags, resolvedToken));
- }
- //
- // If we have a list, try to resolve each element of the list in turn
- //
- else
- {
- OSErr err = noErr;
-
- Try
- {
- FOREACHDESCRIPTOR(this, descriptor)
- {
- //
- // We do not want to dispose of the intermediate token descriptor
- // because its data is adopted by the 'result' token descriptor.
- //
- intermediate = descriptor.Resolve(callbackFlags);
- resolvedToken.AdoptToken(intermediate);
- intermediate.MakeNull();
- }
- }
- Catch(err)
- {
- descriptor.Dispose();
- intermediate.DisposeToken();
- resolvedToken.DisposeToken();
- Throw(err);
- }
- }
-
- return resolvedToken;
- } // TDescriptor::Resolve
-
-
- //========================================================================================
- // CLASS TAEvent
- //
- // AppleEvents are just like AERecords, but they can contain attributes as well as
- // parameters.
- //========================================================================================
-
-
- //----------------------------------------------------------------------------------------
- // TAEvent::TAEvent:
- //----------------------------------------------------------------------------------------
- TAEvent::TAEvent()
- {
-
- } // TAEvent::TAEvent
-
-
- //----------------------------------------------------------------------------------------
- // TAEvent::MakeAppleEvent:
- //----------------------------------------------------------------------------------------
- void TAEvent::MakeAppleEvent(AEEventClass eventClass, AEEventID eventID,
- const TDescriptor& target, short returnID, long transactionID)
- {
- FailErr(AECreateAppleEvent(eventClass, eventID,
- (const AEAddressDesc *) &target, returnID, transactionID, *this));
- } // TAEvent::MakeAppleEvent
-
- //----------------------------------------------------------------------------------------
- // TAEvent::MakeAppleEvent:
- //----------------------------------------------------------------------------------------
- void TAEvent::MakeAppleEvent(AEEventClass eventClass, AEEventID eventID,
- const ProcessSerialNumber& psn, short returnID, long transactionID)
- {
- TDescriptor address;
- address.CopyData(typeProcessSerialNumber, (Ptr) &psn, sizeof(ProcessSerialNumber));
-
- this->MakeAppleEvent(eventClass, eventID, address, returnID, transactionID);
-
- address.Dispose();
- } // TAEvent::MakeAppleEvent
-
-
- #define kCheckAEM 0
- #define kDontUseSelfSend 1
- #define kSelfSendSafe 2
-
- short gCanUseSelfSend = kCheckAEM;
-
- //----------------------------------------------------------------------------------------
- // TAEvent::MakeEventAddressedToSelf:
- //----------------------------------------------------------------------------------------
- void TAEvent::MakeEventAddressedToSelf(AEEventClass eventClass, AEEventID eventID, short returnID, long transactionID)
- {
- ProcessSerialNumber current; // create psn for the current process
- current.highLongOfPSN = 0;
- current.lowLongOfPSN = kCurrentProcess;
-
- //
- // Old versions of the AEM leak memory if send-to-self is used
- //
- if(gCanUseSelfSend == kCheckAEM)
- {
- long aevtSelector = 0;
- OSErr err = Gestalt('evnt', &aevtSelector);
- gCanUseSelfSend = ((aevtSelector & 2) != 0) ? kSelfSendSafe : kDontUseSelfSend;
- }
-
- //
- // Don't make the self-addressed event unless it is safe to do so
- //
- if(gCanUseSelfSend == kSelfSendSafe)
- {
- this->MakeAppleEvent(eventClass, eventID, current, returnID, transactionID);
- }
- else
- FailErr(errAEEventNotHandled);
- } // TAEvent::MakeEventAddressedToSelf
-
- //----------------------------------------------------------------------------------------
- // TAEvent::MakeEventAddressedToSystem:
- //----------------------------------------------------------------------------------------
- void TAEvent::MakeEventAddressedToSystem(AEEventClass eventClass, AEEventID eventID, short returnID, long transactionID)
- {
- ProcessSerialNumber systemPSN; // create psn for the System
- systemPSN.highLongOfPSN = 0;
- systemPSN.lowLongOfPSN = kSystemProcess;
-
- this->MakeAppleEvent(eventClass, eventID, systemPSN, returnID, transactionID);
- } // TAEvent::MakeEventAddressedToSystem
-
- //----------------------------------------------------------------------------------------
- // TAEvent::Send:
- //----------------------------------------------------------------------------------------
- void TAEvent::Send( TAEvent* reply,
- AESendMode sendMode,
- AESendPriority sendPriority,
- long timeOutInTicks,
- AEIdleUPP idleProc,
- AEFilterUPP filterProc)
- {
- FailErr(AESend(*this, *reply, sendMode, sendPriority, timeOutInTicks, idleProc, filterProc));
- } // TAEvent::Send
-
- #define kAEDontExecute 0x2000 // for SendMode, when you just want an event recorded, not executed
-
- //----------------------------------------------------------------------------------------
- // TAEvent::SendNoExecute:
- //
- // This routine sends the event with the 'kAEDontExecute' bit set, so that the
- // event will be recorded, but the recipient will not execute it. The event is
- // also sent 'no reply', since it does not make sense to expect a result from
- // a command that is not actually executed.
- //----------------------------------------------------------------------------------------
- void TAEvent::SendNoExecute()
- {
- //
- // The reply isn't actuall filled in due to the kAENoReply flag
- //
- TAEvent reply;
- Send(&reply, kAENoReply+kAEDontExecute);
- } // TAEvent::SendNoExecute
-
-
- //----------------------------------------------------------------------------------------
- // TAEvent::SuspendTheCurrentEvent:
- //----------------------------------------------------------------------------------------
- void TAEvent::SuspendTheCurrentEvent()
- {
- FailErr(AESuspendTheCurrentEvent(*this));
- } // TAEvent::SuspendTheCurrentEvent
-
- //----------------------------------------------------------------------------------------
- // TAEvent::ResumeTheCurrentEvent:
- //----------------------------------------------------------------------------------------
- void TAEvent::ResumeTheCurrentEvent(TAEvent* reply, AEEventHandlerUPP dispatcher, long refCon)
- {
- FailErr(AEResumeTheCurrentEvent(*this, *reply, dispatcher, refCon));
- } // TAEvent::ResumeTheCurrentEvent
-
- //----------------------------------------------------------------------------------------
- // TAEvent::SetTheCurrentEvent:
- //----------------------------------------------------------------------------------------
- void TAEvent::SetTheCurrentEvent()
- {
- FailErr(AESetTheCurrentEvent(*this));
- } // TAEvent::SetTheCurrentEvent
-
- //----------------------------------------------------------------------------------------
- // TAEvent::ResetTimer:
- //
- // Note: requires that this event be a 'reply' event passed to one of our event
- // handlers by the AppleEvent manager
- //----------------------------------------------------------------------------------------
- void TAEvent::ResetTimer()
- {
- FailErr(AEResetTimer(*this));
- } // TAEvent::ResetTimer
-
- //----------------------------------------------------------------------------------------
- // TAEvent::SpecifyThatParameterIsOptional:
- //----------------------------------------------------------------------------------------
- void TAEvent::SpecifyThatParameterIsOptional(AEKeyword theOptionalKeyword)
- {
- TDescriptor optionalKeywordsList;
- TDescriptor optionalKeyword;
- OSErr err = noErr;
-
- Try
- {
- //
- // ◊Script: We need to test to see if keyOptionalKeywordAttr
- // already exists, and if so, then just add one more element to
- // the list that is already inside the event.
- //
- optionalKeywordsList.MakeList();
- optionalKeyword.MakeKeyword(theOptionalKeyword);
- optionalKeywordsList.AddDescriptor(optionalKeyword);
- optionalKeyword.Dispose();
- this->PutAttribute(keyOptionalKeywordAttr, optionalKeywordsList);
- optionalKeywordsList.Dispose();
- }
- Catch(err)
- {
- optionalKeyword.Dispose();
- optionalKeywordsList.Dispose();
-
- Throw(err);
- }
- } // TAEvent::SpecifyThatParameterIsOptional
-
- //----------------------------------------------------------------------------------------
- // TAEvent::GetAttribute:
- //----------------------------------------------------------------------------------------
- TDescriptor TAEvent::GetAttribute(AEKeyword key, DescType desiredType /* = typeWildCard */)
- {
- TDescriptor result;
-
- FailErr(AEGetAttributeDesc(*this, key, desiredType, result));
-
- return result;
- } // TAEvent::GetAttribute
-
- //----------------------------------------------------------------------------------------
- // TAEvent::GetLongAttribute:
- //----------------------------------------------------------------------------------------
- long TAEvent::GetLongAttribute(AEKeyword key)
- {
- DescType typeCode;
- long actualSize;
- long result;
-
- FailErr(AEGetAttributePtr(*this, key, typeLongInteger, &typeCode, (Ptr)&result, sizeof(long), &actualSize));
-
- return result;
- } // TAEvent::GetLongAttribute
-
- //----------------------------------------------------------------------------------------
- // TAEvent::PutAttribute:
- //----------------------------------------------------------------------------------------
- void TAEvent::PutAttribute(AEKeyword key, TDescriptor attribute)
- {
- FailErr(AEPutAttributeDesc(*this, key, attribute));
- } // TAEvent::PutAttribute
-
- //----------------------------------------------------------------------------------------
- // PutOptionalDescriptor:
- //----------------------------------------------------------------------------------------
- void TAEvent::PutOptionalDescriptor(AEKeyword key, TDescriptor data)
- {
- this->PutDescriptor(key, data);
- this->SpecifyThatParameterIsOptional(key);
- } // TAEvent::PutOptionalDescriptor
-
- //----------------------------------------------------------------------------------------
- // TAEvent::PutLongAttribute:
- //----------------------------------------------------------------------------------------
- void TAEvent::PutLongAttribute(AEKeyword key, long attributeValue)
- {
- FailErr(AEPutAttributePtr(*this, key, typeLongInteger, (Ptr)&attributeValue, sizeof(long)));
- } // TAEvent::PutLongAttribute
-
-
- //========================================================================================
- // CLASS TTokenDescriptor
- //
- // The class TTokenDescriptor represents descriptors returned by AEResolve
- //========================================================================================
-
-
- //----------------------------------------------------------------------------------------
- // TTokenDescriptor::TTokenDescriptor:
- //----------------------------------------------------------------------------------------
- TTokenDescriptor::TTokenDescriptor()
- {
- fDescriptorType = typeNull;
- fDataHandle = nil;
- } // TTokenDescriptor::TTokenDescriptor
-
- //----------------------------------------------------------------------------------------
- // TTokenDescriptor::TTokenDescriptor:
- //----------------------------------------------------------------------------------------
- TTokenDescriptor::TTokenDescriptor(TDescriptor desc)
- {
- this->fDescriptorType = desc.DescriptorType();
- this->fDataHandle = desc.DataHandle();
- } // TTokenDescriptor::TTokenDescriptor
-
- //----------------------------------------------------------------------------------------
- // TTokenDescriptor::DisposeToken:
- //
- // It is very important that token descriptors be disposed of by AEDisposeToken,
- // _not_ AEDisposeDesc.
- //----------------------------------------------------------------------------------------
- void TTokenDescriptor::DisposeToken()
- {
- AEDisposeToken(*this); // Should fail on error? Probably not.
-
- // FailErr(AEDisposeDesc(*this));
- } // TTokenDescriptor::DisposeToken
-
-
- //----------------------------------------------------------------------------------------
- // TTokenDescriptor::TokenHandle:
- //
- // Return the TTokenObject stored inside the token descriptor
- //----------------------------------------------------------------------------------------
- TAbstractScriptableObject* TTokenDescriptor::TokenHandle()
- {
- Handle tokenHandle = this->DataHandle();
- TAbstractScriptableObject* tokenObject = nil;
-
- if((this->DescriptorType() != typeTokenObject) || (tokenHandle == nil))
- {
- //
- // ••• What error code should we fail with here?
- //
- FailErr(errAENoSuchObject);
- }
-
- //
- // tokenHandle is a handle that contains a TTokenObject*,
- // so it is a pointer to a pointer to a TTokenObject* (wow)
- //
- tokenObject = ** ((TAbstractScriptableObject***) tokenHandle);
- return tokenObject;
- } // TTokenDescriptor::TokenHandle
-
-
- //----------------------------------------------------------------------------------------
- // TTokenDescriptor::AdoptToken:
- //
- // IMPORTANT: ADOPTS THE TOKEN PASSED TO IT
- //----------------------------------------------------------------------------------------
- void TTokenDescriptor::AdoptToken(TTokenDescriptor& tokenDescriptor)
- {
- //
- // Don't adopt the new token if it is empty
- //
- if(tokenDescriptor.IsNullDescriptor() == false)
- {
- //
- // If this descriptor is empty, it is easy to adopt the new token
- //
- if( this->IsNullDescriptor() )
- {
- TDescriptor::AdoptHandle(tokenDescriptor.DescriptorType(), tokenDescriptor.DataHandle() );
- tokenDescriptor.MakeNull();
- }
- else
- {
- TAbstractScriptableObject* tokenObject = tokenDescriptor.TokenHandle();
- this->AdoptToken(tokenObject);
-
- //
- // n.b. 'Dispose', not 'DisposeToken'. The token that
- // was formerly contained in tokenDescriptor is now referenced
- // in 'this' token descriptor, so it would be a bad idea to
- // delete it.
- //
- tokenDescriptor.Dispose();
- }
- }
- } // TTokenDescriptor::AdoptToken
-
- //----------------------------------------------------------------------------------------
- // TTokenDescriptor::AdoptToken:
- //----------------------------------------------------------------------------------------
- void TTokenDescriptor::AdoptToken(TAbstractScriptableObject* tokenObject)
- {
- //
- // Don't adopt the new token if it is not a valid object
- //
- if(tokenObject != nil)
- {
- //
- // If this descriptor is empty, then create a new
- // token descriptor to hold a pointer to the tokenObject.
- //
- if(this->IsNullDescriptor() )
- {
- Handle newHandle = NewHandle( sizeof(Ptr) );
- ** ((TAbstractScriptableObject***)newHandle) = tokenObject;
-
- TDescriptor::AdoptHandle(typeTokenObject, newHandle);
- }
- //
- // If there is already something here, then we need
- // to somehow merge the two tokens together. In the
- // Scriptable Finder, we want to create a mark token
- // to do the merge. However, MoreAEM does not depend
- // on files such as MarkToken.h which are outside of
- // the Blue folder. Therefore, we call a callback proc
- // to fill in the mark token. The callback proc is
- // installed in InitializeScriptability.
- //
- else
- {
- if(gMergeTokensProc == nil)
- FailErr(errAEEventNotHandled);
-
- //
- // The MergeTokensProc takes two TAbstractScriptableObject*'s
- // and merges them into another TAbstractScriptableObject*
- // (which adopts the two original tokens).
- //
- TAbstractScriptableObject* mergedTokens = (*gMergeTokensProc)(this->TokenHandle(), tokenObject);
-
- Handle tokenHandle = this->DataHandle();
- ** ((TAbstractScriptableObject***) tokenHandle) = mergedTokens;
- }
- }
- } // TTokenDescriptor::AdoptToken
-
-
- #pragma segment CFrontCruft
-